﻿using Device;
using OfficeOpenXml;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;

namespace T68Control.Procdure
{
    internal class TestModul
    {
        #region Relay

        public static Dictionary<string, Relay> Relays { get; set; }
        public static Dictionary<string, TestParam> TestParams { get; set; }

        public static Dictionary<string, int> DOIndexs { get; set; }

        private static void LoadRelays(ExcelWorksheet ws)
        {
            Relays = new Dictionary<string, Relay>();
            int row = 2;
            while (true)
            {
                ExcelRangeBase cell1 = ws.Cells[row, 1];
                ExcelRangeBase cell2 = ws.Cells[row, 2];
                ExcelRangeBase cell3 = ws.Cells[row, 3];
                if (cell1.Value == null)
                {
                    break;
                }
                if (string.IsNullOrEmpty(cell1.Value.ToString().Trim(' ')))
                {
                    break;
                }
                string key = cell1.Value.ToString().Trim(' ');
                int slaveId = Convert.ToInt32(cell2.Value.ToString());
                int channel = Convert.ToInt32(cell3.Value.ToString());

                Relays.Add(key, new Relay { SlaveId = slaveId, Channel = channel });
                row++;
            }
        }

        private static void LoadTestConfig(ExcelWorksheet ws)
        {
            TestParams = new Dictionary<string, TestParam>();
            int row = 2;
            while (true)
            {
                ExcelRangeBase cell1 = ws.Cells[row, 1];
                ExcelRangeBase cell2 = ws.Cells[row, 2];
                ExcelRangeBase cell3 = ws.Cells[row, 3];
                if (cell1.Value == null)
                {
                    break;
                }
                if (string.IsNullOrEmpty(cell1.Value.ToString().Trim(' ')))
                {
                    break;
                }
                string key = cell1.Value.ToString().Trim(' ');

                TestParam param = new TestParam()
                {
                    Param1 = cell2.Value?.ToString().Trim(' '),
                    Param2 = cell3.Value?.ToString().Trim(' ')
                };

                TestParams.Add(key, param);
                row++;
            }
        }

        private static void LoadDOIndexs(ExcelWorksheet ws)
        {
            DOIndexs = new Dictionary<string, int>();
            int row = 2;
            while (true)
            {
                ExcelRangeBase cell1 = ws.Cells[row, 1];
                ExcelRangeBase cell2 = ws.Cells[row, 2];
                if (cell1.Value == null)
                {
                    break;
                }
                if (string.IsNullOrEmpty(cell1.Value.ToString().Trim(' ')))
                {
                    break;
                }
                string key = cell1.Value.ToString().Trim(' ');
                int doIndex = Convert.ToInt32(cell2.Value.ToString());

                DOIndexs.Add(key, doIndex);
                row++;
            }
        }

        #endregion Relay

        #region TestItems

        public static List<TestItem> TestItems { get; set; }

        private static void LoadTestProcdure(ExcelWorksheet ws)
        {
            TestItems = new List<TestItem>();
            int row = 2;
            while (true)
            {
                ExcelRangeBase cell1 = ws.Cells[row, 1];
                ExcelRangeBase cell2 = ws.Cells[row, 2];
                ExcelRangeBase cell3 = ws.Cells[row, 3];
                ExcelRangeBase cell4 = ws.Cells[row, 4];
                ExcelRangeBase cell5 = ws.Cells[row, 5];
                ExcelRangeBase cell6 = ws.Cells[row, 6];
                ExcelRangeBase cell7 = ws.Cells[row, 7];
                ExcelRangeBase cell8 = ws.Cells[row, 8];
                ExcelRangeBase cell9 = ws.Cells[row, 9];
                ExcelRangeBase cell10 = ws.Cells[row, 10];
                ExcelRangeBase cell11 = ws.Cells[row, 11];
                ExcelRangeBase cell12 = ws.Cells[row, 12];

                if (cell1.Value == null)
                {
                    break;
                }
                if (string.IsNullOrEmpty(cell1.Value.ToString().Trim(' ')))
                {
                    break;
                }
                TestItem testItem = new TestItem();
                testItem.No = Convert.ToInt32(cell1.Value.ToString().Trim(' '));
                testItem.GroupNo = Convert.ToInt32(cell2.Value.ToString().Trim(' '));
                testItem.Item = cell3.Value?.ToString();
                testItem.Type = cell4.Value?.ToString().Trim(' ');
                testItem.OperationFun = cell5.Value?.ToString();
                testItem.Operator = cell6.Value?.ToString();
                testItem.Param1 = cell7.Value?.ToString();
                testItem.Param2 = cell8.Value?.ToString();
                testItem.Param3 = cell9.Value?.ToString();
                testItem.Param4 = cell10.Value?.ToString();
                testItem.Desc = cell11.Value?.ToString();
                testItem.Result = null;
                testItem.Message = null;
                testItem.IsChecked = cell12.Value?.ToString() == "1" ? true : false;
                if (testItem.Type == "测试")
                {
                    if (testItem.Operator == "Range")
                    {
                        testItem.PassCondition = $"{testItem.Param1}～{testItem.Param2}";
                    }
                    else
                    {
                        testItem.PassCondition = $"{testItem.Operator}{testItem.Param1}";
                    }
                }
                if (!TestFuncs.ContainsKey(testItem.OperationFun))
                {
                    throw new Exception($"测试方法未找到[{testItem.OperationFun}]");
                }
                testItem.Excute = TestFuncs[testItem.OperationFun];
                TestItems.Add(testItem);
                row++;
            }
        }

        #endregion TestItems

        public static void ParseExcelFile(string path)
        {
            ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
            if (!File.Exists(path))
            {
                throw new FileNotFoundException(path);
            }
            using (ExcelPackage package = new ExcelPackage(path))
            {
                //ExcelWorksheet wsTestProcdure = package.Workbook.Worksheets["测试流程"];
                ExcelWorksheet wsRelayConfig = package.Workbook.Worksheets["继电器定义"];
                ExcelWorksheet wsTestConfig = package.Workbook.Worksheets["测试参数"];
                //ExcelWorksheet wsDODefine = package.Workbook.Worksheets["DO定义"];
                LoadRelays(wsRelayConfig);
                LoadTestConfig(wsTestConfig);
                //LoadTestProcdure(wsTestProcdure);
                //LoadDOIndexs(wsDODefine);
            }
        }

        #region Func

        public static Dictionary<string, Func<TestItem, bool>> TestFuncs { get; set; }

        static TestModul()
        {
            TestFuncs = new Dictionary<string, Func<TestItem, bool>>();
            TestFuncs.Add("SetBusVol", FuncSetBusVol);
            TestFuncs.Add("SetRelay", FuncSetRelay);
            TestFuncs.Add("GetVol", FuncGetVol);
            TestFuncs.Add("Sleep", FuncSleep);
            TestFuncs.Add("SetIV3003T", FuncSetIV3003T);
            TestFuncs.Add("SetDO", FuncSetDO);
        }

        private static bool FuncSetDO(TestItem item)
        {
            Machine.IOModule.SetDOValue(DOIndexs[item.Param1], Convert.ToInt32(item.Param2));
            return true;
        }

        private static bool FuncSetIV3003T(TestItem item)
        {
            int chl = Convert.ToInt32(item.Param1);
            double vol = Convert.ToDouble(item.Param2);
            double cur = Convert.ToDouble(item.Param3);
            IV_3003T.SwitchCh((IV3003T_CH_ENUM)chl);
            IV_3003T.SetVoltage(vol);
            IV_3003T.SetCurrent(cur);
            IV_3003T.SetChStatus(1);
            return true;
        }

        private static bool FuncSleep(TestItem item)
        {
            Thread.Sleep(Convert.ToInt32(item.Param1));
            return true;
        }

        private static bool FuncGetVol(TestItem item)
        {
            DM3058E.SetFunction(Function.DCV);
            double vol = DM3058E.GetValue();
            item.Message = $"实测值[{vol}V]";
            switch (item.Operator)
            {
                case "Range":
                    double cmpVal1 = Convert.ToDouble(item.Param1);
                    double cmpVal2 = Convert.ToDouble(item.Param2);
                    double min = Math.Min(cmpVal1, cmpVal2);
                    double max = Math.Max(cmpVal1, cmpVal2);
                    return vol >= min & vol <= max;

                case ">=":
                    double cmpVal = Convert.ToDouble(item.Param1);
                    return vol >= cmpVal;

                case ">":
                    cmpVal = Convert.ToDouble(item.Param1);
                    return vol > cmpVal;

                case "<=":
                    cmpVal = Convert.ToDouble(item.Param1);
                    return vol <= cmpVal;

                case "<":
                    cmpVal = Convert.ToDouble(item.Param1);
                    return vol < cmpVal;

                default:
                    return false;
            }
        }

        private static bool FuncSetRelay(TestItem item)
        {
            string key = item.Param1;
            Relay relay = Relays[key];
            PQW_IO.SetDO(relay.SlaveId, relay.Channel, item.Param2 == "1");
            return true;
        }

        private static bool FuncSetBusVol(TestItem item)
        {
            RU_18_10001.SetVoltage(Convert.ToInt32(item.Param1));
            RU_18_10001.SetCurrent(Convert.ToInt32(item.Param2));
            RU_18_10001.SetStatus(true);
            return true;
        }

        #endregion Func
    }
}